namespace SimpleWebServices.Models
{
    using System;
    using System.Collections.ObjectModel;
    using System.Text;
    using System.Web;
    using System.Xml;
    using System.Xml.Serialization;
    using System.Xml.XPath;
    using Moq;
    using SimpleWebServices;
    using SimpleWebServices.Web;
    using Xunit;

    public sealed class StyleSheetFacts
    {
        [Fact]
        public void typedef()
        {
            Assert.True(new ObjectExpectations<StyleSheet>()
                .DerivesFrom<object>()
                .IsConcreteClass()
                .IsSealed()
                .HasDefaultConstructor()
                .XmlRoot("stylesheet")
                .Implements<IXmlSerializable>()
                .Result);
        }

        [Fact]
        public void deserialize()
        {
            StyleSheet actual = (
                "<stylesheet if='lte IE 7' media='screen' href='/-/screen.css'>" +
                    "<import>http://static.example.com/-/stylesheet/screen1.css</import>" +
                    "<import>http://static.example.com/-/stylesheet/screen2.css</import>" +
                "</stylesheet>").Deserialize<StyleSheet>();

            Assert.Equal<string>("lte IE 7", actual.Conditional);
            Assert.Equal<string>("/-/screen.css", actual.Href);
            Assert.Equal<string>("screen", actual.Media);
            Assert.Equal<string>("http://static.example.com/-/stylesheet/screen1.css", actual.Imports[0]);
            Assert.Equal<string>("http://static.example.com/-/stylesheet/screen2.css", actual.Imports[1]);
        }

        [Fact]
        public void deserializeEmpty()
        {
            StyleSheet actual = "<stylesheet />".Deserialize<StyleSheet>();

            Assert.Null(actual.Conditional);
            Assert.Null(actual.Href);
            Assert.Null(actual.Media);
            Assert.Empty(actual.Imports);
        }

        [Fact]
        public void serialize()
        {
            StyleSheet obj = new StyleSheet
            {
                Conditional = "lte IE 7",
                Href = "/-/screen.css",
                Media = "screen"
            };
            obj.Imports.Add("http://static.example.com/-/stylesheet/screen1.css");
            obj.Imports.Add("http://static.example.com/-/stylesheet/screen2.css");

            XPathNavigator navigator = obj.Serialize().CreateNavigator();

            Assert.True((bool)navigator.Evaluate("2=count(/stylesheet/import)"));
            Assert.True((bool)navigator.Evaluate("2=count(/stylesheet[@if='lte IE 7'][@media='screen'][@href='/-/screen.css']/import)"));
            Assert.True((bool)navigator.Evaluate("'http://static.example.com/-/stylesheet/screen1.css'=/stylesheet[@if='lte IE 7'][@media='screen'][@href='/-/screen.css']/import[1]"));
            Assert.True((bool)navigator.Evaluate("'http://static.example.com/-/stylesheet/screen2.css'=/stylesheet[@if='lte IE 7'][@media='screen'][@href='/-/screen.css']/import[2]"));
        }

        [Fact]
        public void ctor()
        {
            Assert.NotNull(new StyleSheet());
        }

        [Fact]
        public void prop_Conditional()
        {
            Assert.True(new PropertyExpectations(typeof(StyleSheet).GetProperty("Conditional"))
                .IsAutoProperty<string>()
                .Result);
        }

        [Fact]
        public void prop_Href()
        {
            Assert.True(new PropertyExpectations(typeof(StyleSheet).GetProperty("Href"))
                .IsAutoProperty<string>()
                .Result);
        }

        [Fact]
        public void prop_Media()
        {
            Assert.True(new PropertyExpectations(typeof(StyleSheet).GetProperty("Media"))
                .IsAutoProperty<string>()
                .Result);
        }

        [Fact]
        public void prop_Imports()
        {
            Assert.True(new PropertyExpectations(typeof(StyleSheet).GetProperty("Imports"))
                .TypeIs<Collection<string>>()
                .DefaultValueIsNotNull()
                .Result);
        }

        [Fact]
        public void op_ToString()
        {
            try
            {
                var mock = new Mock<HttpContextBase>();
                mock.SetupGet<bool>(x => x.Request.IsSecureConnection).Returns(true).Verifiable();
                HttpContextFactory.Mock = mock.Object;

                StyleSheet actual = new StyleSheet();
                actual.Imports.Add("http://static.example.com/-/screen1.css");
                actual.Imports.Add("http://static.example.com/-/screen2.css");

                StringBuilder expected = new StringBuilder();
                expected.AppendLine("@import \"https://static.example.com/-/screen1.css\";");
                expected.AppendLine("@import \"https://static.example.com/-/screen2.css\";");

                Assert.Equal<string>(expected.ToString(), actual.ToString());

                mock.VerifyAll();
            }
            finally
            {
                HttpContextFactory.Reset();
            }
        }

        [Fact]
        public void op_ToString_whenEmpty()
        {
            Assert.Equal<string>(string.Empty, new StyleSheet().ToString());
        }

        [Fact]
        public void IXmlSerializable_op_GetSchema()
        {
            Assert.Throws<NotSupportedException>(() => (new StyleSheet() as IXmlSerializable).GetSchema());
        }

        [Fact]
        public void IXmlSerializable_op_ReadXml_XmlReaderNull()
        {
            Assert.Throws<ArgumentNullException>(() => (new StyleSheet() as IXmlSerializable).ReadXml(null as XmlReader));
        }

        [Fact]
        public void IXmlSerializable_op_WriteXml_XmlWriterNull()
        {
            Assert.Throws<ArgumentNullException>(() => (new StyleSheet() as IXmlSerializable).WriteXml(null as XmlWriter));
        }
    }
}